<template>
  <div class="map-picker">
    <!-- 左侧地图区域 -->
    <div class="map-section">
      <div class="search-box">
        <a-input-search
          v-model:value="searchKeyword"
          placeholder="请输入地址搜索"
          enter-button
          :loading="searchLoading"
          @search="handleSearch"
        />
      </div>
      
      <!-- 地图操作按钮 -->
      <div class="map-controls">
        <a-space>
          <a-button type="primary" @click="getCurrentLocation" :loading="locationLoading">
            <template #icon><environment-outlined /></template>
            定位当前位置
          </a-button>
          <a-button @click="searchNearbyAddresses" :loading="nearbyLoading">
            <template #icon><search-outlined /></template>
            搜索附近地址
          </a-button>
        </a-space>
      </div>
      
      <div class="map-container" ref="mapContainer"></div>
      
      <div class="search-result" v-if="searchResults.length">
        <a-list size="small">
          <a-list-item v-for="item in searchResults" :key="item.id" @click="handleSelectLocation(item)">
            <a-list-item-meta>
              <template #title>{{ item.name }}</template>
              <template #description>{{ item.address }}</template>
            </a-list-item-meta>
          </a-list-item>
        </a-list>
      </div>
      

    </div>
    
    <!-- 右侧附近地址面板 -->
    <div class="nearby-section">
      <div class="nearby-header">
        <h4>附近地址</h4>
        <span v-if="nearbyAddresses.length > 0" class="address-count">{{ nearbyAddresses.length }}个地址</span>
      </div>
      <div class="nearby-content">
        <div v-if="nearbyAddresses.length === 0" class="empty-state">
          <p>自动搜索中，或点击"搜索附近地址"</p>
          <p style="font-size: 12px; color: #999; margin-top: 8px;">仅显示含有省市区信息的地址</p>
        </div>
        <a-list v-else size="small" :data-source="nearbyAddresses">
          <template #renderItem="{ item }">
            <a-list-item class="nearby-item" @click="selectNearbyAddress(item)">
              <a-list-item-meta>
                <template #title>{{ item.name }}</template>
                <template #description>
                  <div class="address-info">
                    <div class="full-address">{{ item.address }}</div>
                    <div v-if="item.addressComponent && item.addressComponent.province" class="area-info">
                      <a-tag size="small" color="blue">{{ item.addressComponent.province }}</a-tag>
                      <a-tag v-if="item.addressComponent.city && item.addressComponent.city !== item.addressComponent.province" size="small" color="green">{{ item.addressComponent.city }}</a-tag>
                      <a-tag v-if="item.addressComponent.district" size="small" color="orange">{{ item.addressComponent.district }}</a-tag>
                    </div>
                    <div v-if="item.distance" class="distance-info">
                      <a-tag size="small">{{ Math.round(item.distance) }}米</a-tag>
                    </div>
                  </div>
                </template>
              </a-list-item-meta>
              <template #extra>
                <a-button type="link" size="small">选择</a-button>
              </template>
            </a-list-item>
          </template>
        </a-list>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch } from 'vue';
import { message } from 'ant-design-vue';
import { EnvironmentOutlined, SearchOutlined } from '@ant-design/icons-vue';
// @ts-ignore
import { loadAMap, setSecurityConfig } from '@/utils/map-config';

const props = defineProps<{
  modelValue?: {
    address: string;
    location: {
      lng: number;
      lat: number;
    };
  };
}>();

const emit = defineEmits<{
  (e: 'update:modelValue', value: {
    address: string;
    location: {
      lng: number;
      lat: number;
    };
  }): void;
  (e: 'select', value: {
    address: string;
    location: {
      lng: number;
      lat: number;
    };
  }): void;
  (e: 'confirm', value: {
    address: string;
    location: {
      lng: number;
      lat: number;
    };
  }): void;
}>();

// 地图实例
let map: any = null;
let marker: any = null;
let placeSearch: any = null;
let geolocation: any = null;
let AMap: any = null;

const mapContainer = ref<HTMLElement | null>(null);
const searchKeyword = ref('');
const searchResults = ref<any[]>([]);
const selectedLocation = ref<any>(null);

// 附近地址相关状态
const locationLoading = ref(false);
const nearbyLoading = ref(false);
const searchLoading = ref(false);
const nearbyAddresses = ref<any[]>([]);

// 初始化地图
const initMap = async () => {
  try {
    // 设置安全密钥
    setSecurityConfig();
    
    // 加载高德地图
    AMap = await loadAMap();
    
    if (!AMap) {
      throw new Error('地图加载失败');
    }

    map = new AMap.Map(mapContainer.value!, {
      viewMode: '3D', // 是否为3D地图模式
      zoom: 13, // 初始化地图级别
      center: [116.397428, 39.90923], // 初始化地图中心点位置
    });

    // 添加比例尺控件
    const scale = new AMap.Scale({
      position: 'LB' // 左下角
    });
    map.addControl(scale);

    // 添加定位插件（不显示按钮）
    map.plugin(['AMap.Geolocation'], () => {
      geolocation = new AMap.Geolocation({
        enableHighAccuracy: true,
        timeout: 10000,
        showButton: false, // 不显示定位按钮
      });
      // 不添加控件到地图上，保留功能但隐藏按钮
      // map.addControl(geolocation);
    });

    // 添加搜索插件
    map.plugin(['AMap.PlaceSearch'], () => {
      placeSearch = new AMap.PlaceSearch({
        map: map,
        pageSize: 20,
        citylimit: false, // 不限制城市，扩大搜索范围
        extensions: 'all', // 返回详细信息
        type: '', // 不限制POI类型
      });
    });

    // 添加点击事件
    map.on('click', handleMapClick);

    // 创建标记点
    marker = new AMap.Marker({
      map: map,
      draggable: true,
    });

    // 标记点拖动结束事件
    marker.on('dragend', handleMarkerDragEnd);
    
    // 地图初始化完成后自动定位
    setTimeout(() => {
      getCurrentLocation();
    }, 500);
  } catch (error) {
    console.error('初始化地图失败:', error);
    message.error('初始化地图失败: ' + (error.message || '未知错误'));
  }
};

// 搜索地址
const handleSearch = async () => {
  if (!searchKeyword.value.trim()) {
    message.warning('请输入搜索关键词');
    return;
  }
  
  if (!AMap || !map) {
    message.warning('地图未初始化完成，请稍后再试');
    return;
  }

  searchLoading.value = true;
  
  try {
    // 如果placeSearch未初始化，先初始化它
    if (!placeSearch) {
      await new Promise<void>((resolve, reject) => {
        map.plugin(['AMap.PlaceSearch'], () => {
          try {
            placeSearch = new AMap.PlaceSearch({
              map: map,
              pageSize: 20,
              citylimit: false, // 不限制城市，扩大搜索范围
              extensions: 'all', // 返回详细信息
              type: '', // 不限制POI类型
            });
            resolve();
          } catch (error) {
            reject(error);
          }
        });
      });
    }

    const keyword = searchKeyword.value.trim();
    let allResults: any[] = [];
    
    // 多种搜索策略
    const searchStrategies = [
      // 策略1：精确搜索
      () => new Promise<any[]>((resolve) => {
        placeSearch.search(keyword, (status: string, result: any) => {
          if (status === 'complete' && result.poiList && result.poiList.pois) {
            resolve(result.poiList.pois);
          } else {
            resolve([]);
          }
        });
      }),
      
      // 策略2：模糊搜索（去掉一些关键词）
      () => new Promise<any[]>((resolve) => {
        const fuzzyKeyword = keyword.replace(/[省市区县街道路号]/g, '');
        if (fuzzyKeyword !== keyword && fuzzyKeyword.length > 1) {
          placeSearch.search(fuzzyKeyword, (status: string, result: any) => {
            if (status === 'complete' && result.poiList && result.poiList.pois) {
              resolve(result.poiList.pois);
            } else {
              resolve([]);
            }
          });
        } else {
          resolve([]);
        }
      }),
      
      // 策略3：基于当前地图中心点搜索
      () => new Promise<any[]>((resolve) => {
        const currentLocation = getCurrentMapLocation();
        if (currentLocation) {
          placeSearch.searchNearBy(keyword, [currentLocation.lng, currentLocation.lat], 5000, (status: string, result: any) => {
            if (status === 'complete' && result.poiList && result.poiList.pois) {
              resolve(result.poiList.pois);
            } else {
              resolve([]);
            }
          });
        } else {
          resolve([]);
        }
      })
    ];

    // 执行所有搜索策略
    for (const strategy of searchStrategies) {
      try {
        const results = await strategy();
        allResults = allResults.concat(results);
      } catch (error) {
        console.error('搜索策略执行失败:', error);
      }
    }

    // 去重并排序
    const uniqueResults = allResults.filter((item, index, self) => 
      index === self.findIndex(t => t.id === item.id)
    );

    // 按距离排序（如果有当前位置）
    const currentLocation = getCurrentMapLocation();
    if (currentLocation) {
      uniqueResults.sort((a, b) => {
        const distanceA = calculateDistance(currentLocation.lat, currentLocation.lng, a.location.lat, a.location.lng);
        const distanceB = calculateDistance(currentLocation.lat, currentLocation.lng, b.location.lat, b.location.lng);
        return distanceA - distanceB;
      });
    }

    searchResults.value = uniqueResults.slice(0, 20); // 限制显示数量
    
    if (searchResults.value.length === 0) {
      message.info('未找到相关地址，请尝试其他关键词');
    } else {
      message.success(`找到${searchResults.value.length}个相关地址`);
    }
  } catch (error) {
    console.error('搜索失败:', error);
    message.error('搜索失败，请稍后重试');
  } finally {
    searchLoading.value = false;
  }
};

// 计算两点间距离（公里）
const calculateDistance = (lat1: number, lng1: number, lat2: number, lng2: number) => {
  const R = 6371; // 地球半径（公里）
  const dLat = (lat2 - lat1) * Math.PI / 180;
  const dLng = (lng2 - lng1) * Math.PI / 180;
  const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
    Math.sin(dLng/2) * Math.sin(dLng/2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  return R * c;
};

// 选择搜索结果
const handleSelectLocation = (item: any) => {
  if (!map || !marker) return;

  const location = item.location;
  map.setCenter([location.lng, location.lat]);
  marker.setPosition([location.lng, location.lat]);
  
  selectedLocation.value = item;
  searchResults.value = [];
  
  const value = {
    address: item.address,
    location: {
      lng: location.lng,
      lat: location.lat,
    },
  };
  
  emit('update:modelValue', value);
  emit('select', value);
  
  // 自动搜索附近地址
  setTimeout(() => {
    searchNearbyAddresses();
  }, 500);
};

// 地图点击事件
const handleMapClick = (e: any) => {
  if (!marker || !AMap) return;

  const lnglat = e.lnglat;
  marker.setPosition([lnglat.lng, lnglat.lat]);
  
  // 逆地理编码
  const geocoder = new AMap.Geocoder();
  geocoder.getAddress([lnglat.lng, lnglat.lat], (status: string, result: any) => {
    if (status === 'complete') {
      const address = result.regeocode;
      selectedLocation.value = {
        name: address.formattedAddress,
        address: address.formattedAddress,
      };
      
      const value = {
        address: address.formattedAddress,
        location: {
          lng: lnglat.lng,
          lat: lnglat.lat,
        },
      };
      
      emit('update:modelValue', value);
      emit('select', value);
      
      // 自动搜索附近地址
      setTimeout(() => {
        searchNearbyAddresses();
      }, 500);
    }
  });
};

// 标记点拖动结束事件
const handleMarkerDragEnd = (e: any) => {
  if (!AMap) return;
  
  const lnglat = marker.getPosition();
  if (!lnglat) return;

  // 逆地理编码
  const geocoder = new AMap.Geocoder();
  geocoder.getAddress([lnglat.lng, lnglat.lat], (status: string, result: any) => {
    if (status === 'complete') {
      const address = result.regeocode;
      selectedLocation.value = {
        name: address.formattedAddress,
        address: address.formattedAddress,
      };
      
      const value = {
        address: address.formattedAddress,
        location: {
          lng: lnglat.lng,
          lat: lnglat.lat,
        },
      };
      
      emit('update:modelValue', value);
      emit('select', value);
      
      // 自动搜索附近地址
      setTimeout(() => {
        searchNearbyAddresses();
      }, 500);
    }
  });
};

// 监听传入的值
watch(() => props.modelValue, (newVal) => {
  if (newVal && map && marker) {
    const { location } = newVal;
    map.setCenter([location.lng, location.lat]);
    marker.setPosition([location.lng, location.lat]);
  }
  }, { immediate: true });

// 获取当前地图中心点坐标
const getCurrentMapLocation = () => {
  if (!map) return null;
  
  // 优先返回标记点位置，如果没有标记点则返回地图中心点
  if (marker) {
    const markerPosition = marker.getPosition();
    if (markerPosition) {
      return {
        lng: markerPosition.lng,
        lat: markerPosition.lat
      };
    }
  }
  
  // 返回地图中心点位置
  const center = map.getCenter();
  return {
    lng: center.lng,
    lat: center.lat
  };
};

// 搜索附近地址
const searchNearby = (radius = 1000) => {
  return new Promise((resolve, reject) => {
    if (!AMap || !map) {
      reject(new Error('地图未初始化'));
      return;
    }
    
    const currentLocation = getCurrentMapLocation();
    if (!currentLocation) {
      reject(new Error('无法获取当前位置'));
      return;
    }
    
    const nearbySearch = new AMap.PlaceSearch({
      pageSize: 30, // 增加搜索数量，方便过滤
      pageIndex: 1,
      citylimit: false, // 不限制城市范围
      extensions: 'all', // 返回详细信息
      type: '', // 不限制POI类型
    });

    nearbySearch.searchNearBy('', [currentLocation.lng, currentLocation.lat], radius, async (status: string, result: any) => {
      if (status === 'complete' && result.poiList) {
        try {
          // 为每个POI获取完整的地址信息
          const geocoder = new AMap.Geocoder();
          const addressPromises = result.poiList.pois.map((poi: any) => {
            return new Promise((geoResolve) => {
              geocoder.getAddress([poi.location.lng, poi.location.lat], (geoStatus: string, geoResult: any) => {
                let fullAddress = poi.address;
                let province = '';
                let city = '';
                let district = '';
                
                if (geoStatus === 'complete' && geoResult.regeocode) {
                  const regeocode = geoResult.regeocode;
                  const addressComponent = regeocode.addressComponent;
                  
                  if (addressComponent) {
                    province = addressComponent.province || '';
                    city = addressComponent.city || addressComponent.province || '';
                    district = addressComponent.district || '';
                    
                    // 组合完整地址
                    const detailAddress = poi.address || regeocode.formattedAddress || '';
                    fullAddress = `${province}${city}${district}${detailAddress}`;
                  } else {
                    fullAddress = regeocode.formattedAddress || poi.address;
                  }
                }
                
                geoResolve({
                  id: poi.id,
                  name: poi.name,
                  address: fullAddress,
                  shortAddress: poi.address, // 保留原始简短地址
                  location: {
                    lng: poi.location.lng,
                    lat: poi.location.lat
                  },
                  distance: poi.distance,
                  addressComponent: {
                    province,
                    city,
                    district
                  }
                });
              });
            });
          });
          
          const addresses = await Promise.all(addressPromises);
          
          // 过滤只显示含有省市区信息的地址
          const filteredAddresses = addresses.filter((addr: any) => {
            const { province, city, district } = addr.addressComponent;
            // 至少要有省份和城市信息
            return province && city && (province !== city || district);
          });
          
          resolve(filteredAddresses);
        } catch (error) {
          // 如果逆地理编码失败，返回空数组
          console.error('逆地理编码失败:', error);
          resolve([]);
        }
      } else {
        reject(new Error(result?.info || '搜索失败'));
      }
    });
  });
};

// 编程式获取当前位置（不显示按钮）
const getCurrentPosition = () => {
  return new Promise((resolve, reject) => {
    if (!geolocation) {
      reject(new Error('定位功能未初始化'));
      return;
    }
    
    geolocation.getCurrentPosition((status: string, result: any) => {
      if (status === 'complete') {
        resolve(result);
      } else {
        reject(new Error('定位失败'));
      }
    });
  });
};

// 获取当前位置
const getCurrentLocation = async () => {
  if (!navigator.geolocation) {
    message.error('您的浏览器不支持地理定位');
    return;
  }

  locationLoading.value = true;
  try {
    const position = await new Promise<GeolocationPosition>((resolve, reject) => {
      navigator.geolocation.getCurrentPosition(resolve, reject, {
        enableHighAccuracy: true,
        timeout: 10000,
        maximumAge: 60000
      });
    });

    const { latitude, longitude } = position.coords;
    
    // 更新地图位置
    if (map && marker) {
      map.setCenter([longitude, latitude]);
      marker.setPosition([longitude, latitude]);
      
      // 逆地理编码获取地址信息
      await reverseGeocode(longitude, latitude);
      
      // 自动搜索附近地址
      setTimeout(() => {
        searchNearbyAddresses();
      }, 1000);
    }
    
    message.success('定位成功');
  } catch (error) {
    console.error('定位失败:', error);
    message.error('定位失败，请检查位置权限设置');
  } finally {
    locationLoading.value = false;
  }
};

// 逆地理编码
const reverseGeocode = async (lng: number, lat: number) => {
  if (!AMap) return;
  
  const geocoder = new AMap.Geocoder();
  geocoder.getAddress([lng, lat], (status: string, result: any) => {
    if (status === 'complete' && result.regeocode) {
      const address = result.regeocode;
      selectedLocation.value = {
        name: address.formattedAddress,
        address: address.formattedAddress,
      };
      
      const value = {
        address: address.formattedAddress,
        location: {
          lng: lng,
          lat: lat,
        },
      };
      
      emit('update:modelValue', value);
      emit('select', value);
    }
  });
};

// 搜索附近地址
const searchNearbyAddresses = async () => {
  nearbyLoading.value = true;
  try {
    const addresses = await searchNearby(1000);
    nearbyAddresses.value = addresses as any[];
    
    if (nearbyAddresses.value.length > 0) {
      message.success(`找到${nearbyAddresses.value.length}个附近地址`);
    } else {
      message.info('未找到含有完整地址信息的附近位置，您可以手动点击地图选择位置');
    }
  } catch (error) {
    console.error('搜索附近地址失败:', error);
    let errorMsg = '搜索失败';
    
    if (error.message) {
      if (error.message.includes('INVALID_USER_SCODE')) {
        errorMsg = 'API Key无效或权限不足，请检查高德地图控制台配置';
      } else if (error.message.includes('INSUFFICIENT_PRIVILEGES')) {
        errorMsg = 'API Key权限不足，请在高德控制台开启相应服务';
      } else if (error.message.includes('DAILY_QUERY_OVER_LIMIT')) {
        errorMsg = 'API调用次数已达上限，请明天再试或升级配额';
      } else if (error.message.includes('INVALID_USER_DOMAIN')) {
        errorMsg = '域名未在白名单中，请在高德控制台添加当前域名';
      } else {
        errorMsg = `搜索失败: ${error.message}`;
      }
    }
    
    message.error(errorMsg);
  } finally {
    nearbyLoading.value = false;
  }
};

// 选择附近地址
const selectNearbyAddress = (address: any) => {
  if (!map || !marker) return;
  
  // 更新地图位置
  map.setCenter([address.location.lng, address.location.lat]);
  marker.setPosition([address.location.lat, address.location.lng]);
  
  selectedLocation.value = address;
  
  const value = {
    address: address.address,
    location: {
      lng: address.location.lng,
      lat: address.location.lat,
    },
  };
  
  emit('update:modelValue', value);
  emit('select', value);
  emit('confirm', value); // 触发确认事件，通知父组件关闭弹框
  
  message.success(`已选择：${address.name}`);
};

// 暴露方法给父组件
defineExpose({
  getCurrentMapLocation,
  searchNearby,
  getCurrentPosition
});

onMounted(() => {
  initMap();
});

onUnmounted(() => {
  // 清理地图实例
  if (map) {
    map.destroy();
    map = null;
  }
  marker = null;
  placeSearch = null;
  geolocation = null;
  AMap = null;
});
</script>

<style lang="less" scoped>
.map-picker {
  position: relative;
  width: 100%;
  height: 500px;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
  display: flex;

  .map-section {
    flex: 1;
    position: relative;
    min-width: 0;

      .search-box {
    position: absolute;
    top: 10px;
    left: 10px;
    width: 300px;
    z-index: 2;
    
    .search-tips {
      margin-top: 4px;
      color: #666;
      font-size: 12px;
      background: rgba(255, 255, 255, 0.9);
      padding: 4px 8px;
      border-radius: 4px;
      border: 1px solid #e8e8e8;
    }
  }

    .map-controls {
      position: absolute;
      top: 50px;
      left: 10px;
      z-index: 2;
    }

    .map-container {
      width: 100%;
      height: 100%;
    }

    .search-result {
      position: absolute;
      top: 90px;
      left: 10px;
      width: 300px;
      max-height: 300px;
      overflow-y: auto;
      background: #fff;
      border: 1px solid #d9d9d9;
      border-radius: 2px;
      z-index: 2;

      .ant-list-item {
        cursor: pointer;
        padding: 8px 12px;

        &:hover {
          background: #f5f5f5;
        }
      }
    }


  }
  
  .nearby-section {
    width: 320px;
    display: flex;
    flex-direction: column;
    border-left: 1px solid #d9d9d9;
    background: #fafafa;
    
    .nearby-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 12px 16px;
      border-bottom: 1px solid #e8e8e8;
      background: #fff;
      
      h4 {
        margin: 0;
        font-size: 14px;
        font-weight: 500;
        color: rgba(0, 0, 0, 0.85);
      }
      
      .address-count {
        font-size: 12px;
        color: rgba(0, 0, 0, 0.45);
      }
    }
    
    .nearby-content {
      flex: 1;
      overflow: hidden;
      background: #fff;
      
      .empty-state {
        display: flex;
        align-items: center;
        justify-content: center;
        height: 200px;
        color: rgba(0, 0, 0, 0.45);
        text-align: center;
        
        p {
          margin: 0;
        }
      }
      
      .ant-list {
        height: 100%;
        overflow-y: auto;
      }
      
      .nearby-item {
        cursor: pointer;
        border-radius: 0;
        padding: 12px 16px !important;
        margin-bottom: 0;
        border-bottom: 1px solid #f0f0f0;
        transition: all 0.3s;
        
        &:hover {
          background-color: #f5f5f5;
        }
        
        &:last-child {
          border-bottom: none;
        }
      }
      
      .address-info {
        .full-address {
          margin-bottom: 4px;
          color: rgba(0, 0, 0, 0.85);
          font-size: 13px;
          line-height: 1.4;
        }
        
        .area-info {
          margin-bottom: 4px;
          
          .ant-tag {
            margin-right: 4px;
            margin-bottom: 2px;
          }
        }
        
        .distance-info {
          .ant-tag {
            color: rgba(0, 0, 0, 0.45);
            font-size: 11px;
          }
        }
      }
    }
  }
}
</style> 